package com.sxt.controller;


import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.CredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.sxt.entity.SysUser;
import com.sxt.param.LoginParam;
import com.sxt.service.SysMenuService;
import com.sxt.vo.Authority;
import com.sxt.vo.Menu;

import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.CircleCaptcha;

@RestController
public class LoginController {

	private static final String CAPTCHA_CODE = "captcha:";

	@Autowired
	private SysMenuService sysMenuService ;
	
	@Autowired
	private StringRedisTemplate redis ;

	@GetMapping("/login")
	public ResponseEntity<String> toLogin(){
		return ResponseEntity.ok("您还没有登录，请登录...");
	}

	@GetMapping("/unauthorized")
	public ResponseEntity<String> unauthorized(){
		return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("您无权访问");
	}

	/**
	 * uuid 是前端生成的标识，以后要校验验证码，必须使用这个标识来校验
	 * @param uuid
	 * @param response
	 */
	@GetMapping("/captcha.jpg")
	public void getCaptcha(@RequestParam(required = true)String uuid,HttpServletResponse response) {
		CircleCaptcha createCircleCaptcha = CaptchaUtil.createCircleCaptcha(200, 50, 1, 0);
		try {
			ServletOutputStream outputStream = response.getOutputStream();
			createCircleCaptcha.write(outputStream);
			String code = createCircleCaptcha.getCode();
			// 将验证码放在redis里面
			redis.opsForValue().set(CAPTCHA_CODE+uuid, code, 60,TimeUnit.SECONDS);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	/**
	 * 前端传输了一个json的值过来
	 * @param loginParam
	 * @return
	 */
	@PostMapping("/login")
	public ResponseEntity<String> doLogin(@RequestBody LoginParam loginParam) {
		// 验证码并不会返回值，而是错误了，抛异常
		try {
			validateCode(loginParam.getSessionUUID(),loginParam.getImageCode());
			UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(loginParam.getPrincipal(), loginParam.getCredentials());
			Subject subject = SecurityUtils.getSubject();
			// 登录的异常：1  用户不存在  2 密码错误 3 其他错误
			subject.login(usernamePasswordToken);//----> 底层调用的使用Realm
			String token = subject.getSession().getId().toString(); // 该id 若我给前端，前端把它放在头里面，以后访问时，服务器从前端的头里面可以取到该值
			return ResponseEntity.ok(token);
		} catch (AccountException e) {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body("账号不存在");
		}catch (CredentialsException e) {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body("密码错误");
		}catch (AuthenticationException e) {
			return ResponseEntity.status(HttpStatus.BAD_REQUEST.value()).body(e.getMessage());
		}
	}

	/**
	 * 菜单数据的加载
	 * @return
	 */
	@GetMapping("/sys/menu/nav")
	public ResponseEntity<Map<String,Object>> loadMenusAndAuthorities() {
		SysUser sysUser = (SysUser)SecurityUtils.getSubject().getPrincipal();
		Map<String, Object> result = new HashMap<String,Object>();
		// 从数据库查询到该值
		List<Menu> menus = sysMenuService.findMenusByUser(sysUser.getUserId());
		List<Authority> authorities = sysMenuService.findAuthByUser(sysUser.getUserId());
		result.put("authorities", authorities);
		result.put("menuList", menus);
		return ResponseEntity.ok(result);
	}
  
	@GetMapping("sys/user/info")
	public ResponseEntity<SysUser> getCurrentUser(){
		SysUser sysUser = (SysUser)SecurityUtils.getSubject().getPrincipal();
		// user 的密码，phone ，邮箱，盐，需要加密处理
		sysUser.setPassword("***");
		sysUser.setEmail("***");
		return ResponseEntity.ok(sysUser);
	}
	
	private void validateCode(String sessionUUID, String imageCode) {
		// 验证码参数校验
		if(StringUtils.hasText(sessionUUID) && StringUtils.hasText(imageCode)) {
			String redisCode = redis.opsForValue().get(CAPTCHA_CODE+sessionUUID); // redis 里面没有该值== null
			redis.delete(CAPTCHA_CODE+sessionUUID);// 删除验证码
			// redis 里面的值可能为null
			if(imageCode.equalsIgnoreCase(redisCode)) {
				return ;
			}

		}
		throw new AuthenticationException("验证码错误!");
	}

	public static void main(String[] args) {
		Md5Hash md5Hash = new Md5Hash("123456", "whsxt", 2);
		System.out.println(md5Hash.toString());
	}
}
